<?php

namespace app\common\utils;

use app\common\constant\ErrorCode;
use think\exception\ValidateException;

/**
 * 接口成功和失败的返回方法封装
 */
class ApiReturn
{
    /**
     * 成功返回
     * @param null $code
     */
    public static function retSuccess($data = null, $code = null)
    {
        if (!$code) {
            $code = ErrorCode::CODE_SUCCESS;
        }
        $message = ErrorCode::$message[$code] ?? '未知错误';
        self::outPut($code, $data, $message);
    }

    public static function retData($data = null)
    {
        header('Content-Type:application/json;charset=utf-8');
        exit($data);
    }

    /**
     * 异常和错误返回
     * @param \Exception | \Error $e
     */
    public static function retError($e)
    {
        $code = (int)@$e->getCode();
        $message = @$e->getMessage() ?: '';

        //参数校验失败
        if ($e instanceof ValidateException) {
            $ret_code = ErrorCode::CODE_PARAMS_ERROR;
            $ret_message = ErrorCode::$message[$ret_code] . ':' . $message;
            self::outPut($ret_code, [], $ret_message);
        }

        //正常返回的自定义异常,无需特殊处理,直接返回即可
        if ($e instanceof MyException) {
            self::outPut($code, [], $message);
        }

        //写入异常log
        MyLog::record()->error(MyLog::getTraceAsArray($e), 'retError');

        //todo 错误信息通知到钉钉/企业微信
        $notice_error_msg = '【接口报错】' . self::_getSimpleErrorBacktrace($e);

        //返回结果
        self::outPut($code, [], $message);
    }

    /**
     * 获取异常信息的调用栈精简信息
     * @param \Exception | \Error $e
     */
    private static function _getSimpleErrorBacktrace($e)
    {
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
        $backtrace_file = @explode('/', $backtrace[0]['file']);
        $backtrace_file = @$backtrace_file[count($backtrace_file) - 3] . '/' . @$backtrace_file[count($backtrace_file) - 1];
        $back_simple = @$backtrace_file . ':' . @$backtrace[0]['line'] . '->' . @$backtrace[1]['function'];
        $err_detail = MyLog::getTraceAsArray($e);
        $notice_error_msg = $back_simple . '; code:' . @$e->getCode() . '; msg:' . @$e->getMessage() . "; \n";
        $notice_error_msg .= @$err_detail['k1'] . "\n" . @$err_detail['k2'] . "\n" . @$err_detail['k3'];
        return $notice_error_msg;
    }


    /**
     * 统一输出方法
     * @param int $code
     * @param mixed $data
     * @param string $msg
     * @param array $extra 扩展数据
     * @return void
     */
    public static function outPut(int $code, $data = null, string $msg = '', array $extra = [])
    {
        $time_cost = intval(microtime(true) * 1000 - Init::$request_start_time);

        $ret = [];
        $ret['code'] = $code;
        $ret['msg'] = $msg;
        $ret['time_cost'] = $time_cost; //接口耗时,毫秒
        $ret['data'] = $data;
        if (!empty($extra)) {
            $ret['extra'] = $extra;
        }
        $out_json = echoJson($ret);

        //将返回值写入到log
        MyLog::record()->info($out_json, 'response');

        //todo 接口耗时超过设定时长通知到 企业微信/钉钉/邮箱/电话

        //返回结果
        if (!headers_sent()) {
            header('Content-Type:application/json;charset=utf-8');
        }

        exit($out_json);
    }
}